package org.jlatexmath.html;

import android.content.Context;
import android.graphics.Color;
import android.text.Editable;
import android.text.Html;
import android.text.Layout;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.UnderlineSpan;

import org.xml.sax.Attributes;

import java.util.HashMap;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HtmlTagFormatter {
    private static final String TAG_HANDLE_SPAN = "span";
    private static final String TAG_HANDLE_STYLE = "style";
    private static final String TAG_HANDLE_ALIGN = "align";
    private static final String TAG_FONT_SIZE = "font-size";
    private static final String TAG_BACKGROUND_COLOR = "background-color";
    private static final String Tag_FONT_COLOR = "color";
    private static final String TAG_TEXT_ALIGN = "text-align";
    private static final String TAG_TEXT_DECORATION = "text-decoration";


    //表格(带有 thead、tbody 以及 tfoot 元素的 HTML 表格未考虑)
    private static final String TAG_TABLE = "table";
    private static final String TAG_TR = "tr";
    private static final String TAG_TD = "td";


    private String styleContent = "";
    private Vector<String> mListParents = new Vector<String>();//用来标记列表(有序和无序列表)
    private int mListItemCount = 0;//用来标记列表(有序和无序列表)
    HashMap<String, String> mTagStyle = new HashMap<>();
    HashMap<String, Integer> mTagStartIndex = new HashMap<>();//用来保存标签开始标记

    public Spanned handlerHtmlContent(final Context context, String htmlContent, Html.ImageGetter imageGetter) throws NumberFormatException {
        return HtmlParser.buildSpannedText(htmlContent, imageGetter, new HtmlParser.TagHandler() {
            @Override
            public boolean handleTag(boolean opening, String tag, Editable output, Attributes attributes) {
                if (tag.equals(TAG_HANDLE_SPAN)) {
                    //<style>标签的处理方式
                    if (opening) {
                        mTagStartIndex.put(tag, output.length());
                        styleContent = HtmlParser.getValue(attributes, TAG_HANDLE_STYLE);
                        mTagStyle.put(tag, styleContent);
                    } else {
                        handleStyleTag(output, tag, context);
                        mTagStyle.put(tag, "");
                    }
                }
                if (tag.equals("p")) {
                    if (opening) {
                        mTagStartIndex.put(tag, output.length());
                        styleContent = HtmlParser.getValue(attributes, TAG_HANDLE_STYLE);
                        mTagStyle.put(tag, styleContent);
                    } else {
                        handleStyleTag(output, tag, context);
                        mTagStyle.put(tag, "");
                    }
                }
                //-----------------------------------------
//                if (tag.equals(TAG_TABLE)) {
//                    if (opening) {
//                        mTagStartIndex.put(tag, output.length());
//                        styleContent = HtmlParser.getValue(attributes, TAG_HANDLE_STYLE);
//                        mTagStyle.put(tag, styleContent);
//                    } else {
//                        handleStyleTag(output, tag, context);
//                        mTagStyle.put(tag, "");
//                    }
//                }
//                if (tag.equals(TAG_TR)) {
//                }
//                if (tag.equals(TAG_TD)) {
//                }
                //-----------------------------------------

                //列表标签的解析渲染
                if (tag.equals("ul") || tag.equals("ol") || tag.equals("dd")) {
                    if (opening) {
                        mListParents.add(tag);
                    } else mListParents.remove(tag);

                    mListItemCount = 0;
                } else if (tag.equals("li") && !opening) {
                    handleListTag(output);
                }
                return false;
            }
        });
    }

    //正则获取字体
    private static String getAllNumbers(String body) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(body);
        while (matcher.find()) {
            return matcher.group(0);
        }
        return "";
    }

    //处理列表标签
    private void handleListTag(Editable output) {
        if (mListParents.lastElement().equals("ul")) {
            output.append("\n");
            String[] split = output.toString().split("\n");

            int lastIndex = split.length - 1;
            int start = output.length() - split[lastIndex].length() - 1;
            output.setSpan(new BulletSpan(15), start, output.length(), 0);
        } else if (mListParents.lastElement().equals("ol")) {
            mListItemCount++;
            output.append("\n");
            String[] split = output.toString().split("\n");

            int lastIndex = split.length - 1;
            int start = output.length() - split[lastIndex].length() - 1;
            output.insert(start, mListItemCount + ". ");
            output.setSpan(new LeadingMarginSpan.Standard(15 * mListParents.size()), start, output.length(), 0);
        }
    }

    //处理<text-align>
    private void handleAlignTag(Editable output, String parentTag, String alignTag) {
        int startIndex = mTagStartIndex.get(parentTag);
        int stopIndex = output.length();
        AlignmentSpan.Standard as = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL);
        if (alignTag.equals("center")) {
            as = new AlignmentSpan.Standard(
                    Layout.Alignment.ALIGN_CENTER);
        } else if (alignTag.equals("right")) {
            as = new AlignmentSpan.Standard(
                    Layout.Alignment.ALIGN_OPPOSITE);
        } else if (alignTag.equals("left")) {
            as = new AlignmentSpan.Standard(
                    Layout.Alignment.ALIGN_NORMAL);
        }
        // 参考:https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/text/SpannableStringBuilder.java
        // throw new RuntimeException("PARAGRAPH span must start at paragraph boundary");
        // AlignmentSpan继承ParagraphStyle;会检查前后是不是有换行符\n;没有的话抛出以上异常
//        if(!"\n".equals(""+output.charAt(stopIndex-1))) {
//            output.append("\n");
//            stopIndex++;
//
//        }
//        if(!"\n".equals(""+output.charAt(0))){
//            output.insert(0,"\n");
//            stopIndex++;
//            startIndex--;
//        }
        output.setSpan(as, startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    //处理<text-decoration>
    private void handleDecorationTag(Editable output, String parentTag, String decorationTag) {
        int startIndex = mTagStartIndex.get(parentTag);
        int stopIndex = output.length();
        //http://www.w3school.com.cn/tiy/t.asp?f=csse_text-decoration

        if (decorationTag.equals("overline")) {//上划线（顶划线）

        } else if (decorationTag.equals("line-through")) {//中划线（删除线）
            StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
            output.setSpan(strikethroughSpan, startIndex, stopIndex, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        } else if (decorationTag.equals("underline")) {//下划线
            //对于全是空格的下划线的情况是显示不出下划线的，解决方法就是将全是整段空格转换下划线字符
            boolean isDecorationTextAllSpace = true;
            CharSequence decorationText = output.subSequence(startIndex, stopIndex);
            StringBuilder space = new StringBuilder();
            for (char item : decorationText.toString().toCharArray()) {
                if (item != 32 && item != 160) {
                    isDecorationTextAllSpace = false;
                } else {
                    space.append("_");
                }
            }
            if (isDecorationTextAllSpace) {
                //转换下划线字符
                output.replace(startIndex, stopIndex, space);
                //output.setSpan(new ForegroundColorSpan(Color.parseColor("#88000000")), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            } else {
                UnderlineSpan underlineSpan = new UnderlineSpan();
                output.setSpan(underlineSpan, startIndex, stopIndex, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            }
            //
        } else if (decorationTag.equals("blink")) {//文字闪烁

        } else if (decorationTag.equals("none")) {

        }
        //output.setSpan(as, startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    private void handleStyleTag(Editable output, String tag, Context context) {
        String styleContent = mTagStyle.get(tag);
        int startIndex = mTagStartIndex.get(tag);
        int stopIndex = output.length();
        if (!TextUtils.isEmpty(styleContent)) {
            String[] styleValues = styleContent.split(";");
            for (String styleValue : styleValues) {
                String[] tmpValues = styleValue.split(":");
                if (tmpValues != null && tmpValues.length > 0) { //�?要标�?+数据才可食用(font-size=14px)
                    //如果要出来文字大小打开下面的注释
                    /*if (TAG_FONT_SIZE.equals(tmpValues[0])) { //处理文字大小
                        int size = Integer.valueOf(getAllNumbers(tmpValues[1]));
                        Log.i("tag", size + "");
                        output.setSpan(new AbsoluteSizeSpan(sp2px(context, size)), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else */
                    if (TAG_BACKGROUND_COLOR.equals(tmpValues[0])) { //处理背景效果
                        output.setSpan(new BackgroundColorSpan(Color.parseColor(tmpValues[1])), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (Tag_FONT_COLOR.equals(tmpValues[0])) {
                        String str = output.toString();
                        output.setSpan(new ForegroundColorSpan(Color.parseColor(tmpValues[1])), startIndex, stopIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    } else if (TAG_TEXT_ALIGN.equals(tmpValues[0])) {
                        handleAlignTag(output, tag, tmpValues[1]);
                    } else if (TAG_TEXT_DECORATION.equals(tmpValues[0])) {
                        handleDecorationTag(output, tag, tmpValues[1]);
                    }
                }
            }
        }
    }

    public static int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
}
